package com.wechat.config;

import java.io.File;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.util.Properties;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.core.Ordered;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.util.ClassUtils;

import com.swak.codec.Digests;
import com.swak.config.setting.Settings;
import com.swak.utils.JDBCDrivers;
import com.swak.utils.StringUtils;
import com.wechat.Cons;
import com.wechat.login.Login;
import com.wechat.login.LoginService;

public class SubjectEnvPostProcessor
		implements EnvironmentPostProcessor, ApplicationListener<ContextClosedEvent>, Ordered {

	@Override
	public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {

		// 用户ID -- 如果程序已经启动，在这一步会退出
		Login login = LoginService.login();

		// 存储目录
		File storagePath = this.newStorageFile();

		// 用户空间
		File homeFile = new File(storagePath, login.getId());
		if (!homeFile.exists()) {
			homeFile.mkdirs();

			// 不存在用户空间
			login.setFirstLogin(true);
		}

		// 设置用户配置
		this.enableUserStorage(homeFile, login, environment);
	}

	private void enableUserStorage(File homeFile, Login login, ConfigurableEnvironment environment) {
		this.enableUserStorageUseRemoteDB(homeFile, login, environment);
		this.enableUserStorageUseLocalDB(homeFile, login, environment);
	}

	private void enableUserStorageUseRemoteDB(File homeFile, Login login, ConfigurableEnvironment environment) {
		if (!ClassUtils.isPresent("com.mysql.cj.jdbc.Driver", ConfigurableEnvironment.class.getClassLoader())) {
			return;
		}

		// 用户的存储配置
		File storageFile = new File(homeFile, Cons.Storage_Name);
		Properties properties = new Properties();
		properties.put("spring.datasource.url", this.updateDatasourceUrl(environment, login));
		properties.put("spring.storage.path", "file:" + storageFile.getPath());

		// 生效用户配置
		PropertiesPropertySource propertiesPropertySource = new PropertiesPropertySource("user.settings", properties);
		environment.getPropertySources().addFirst(propertiesPropertySource);
	}

	private String updateDatasourceUrl(ConfigurableEnvironment environment, Login login) {
		String url = environment.getProperty("spring.datasource.url");
		String username = environment.getProperty("spring.datasource.username");
		String password = environment.getProperty("spring.datasource.password");
		String dbname = login.getId();
		Connection connection = null;
		Statement statement = null;
		try {
			Class.forName(JDBCDrivers.getDriverClassName(url));
			connection = DriverManager.getConnection(url, username, password);
			String sql = StringUtils.format(
					"create database if not exists %s default character set utf8 COLLATE utf8_general_ci", dbname);
			connection.setAutoCommit(false);
			statement = connection.createStatement();
			statement.execute(sql);
			connection.commit();
		} catch (Exception e) {
		} finally {
			try {
				connection.close();
			} catch (Exception e2) {
			}
			try {
				statement.close();
			} catch (Exception e2) {
			}
		}
		return StringUtils.format("%s/%s", url, dbname);
	}

	private void enableUserStorageUseLocalDB(File homeFile, Login login, ConfigurableEnvironment environment) {
		if (!ClassUtils.isPresent("org.h2.Driver", ConfigurableEnvironment.class.getClassLoader())) {
			return;
		}

		// 创建用户配置
		File dbFile = new File(homeFile, Cons.Msg_Name);
		File storageFile = new File(homeFile, Cons.Storage_Name);
		Properties properties = new Properties();
		properties.put("spring.datasource.url", "jdbc:h2:file:" + dbFile.getPath());
		properties.put("spring.datasource.username", login.getId());
		properties.put("spring.datasource.password", Digests.md5(login.getId()));
		properties.put("spring.storage.path", "file:" + storageFile.getPath());

		// 生效用户配置
		PropertiesPropertySource propertiesPropertySource = new PropertiesPropertySource("user.settings", properties);
		environment.getPropertySources().addFirst(propertiesPropertySource);
	}

	private File newStorageFile() {
		Settings settings = Settings.intSettings();
		File storageFile = new File(settings.getBasePath(), Cons.Storage_Path);
		if (StringUtils.isNotBlank(settings.getConfig(Cons.Storage_Path_Key))) {
			storageFile = new File(settings.getConfig(Cons.Storage_Path_Key));
		}
		if (!storageFile.exists()) {
			storageFile.mkdirs();
		}
		return storageFile;
	}

	@Override
	public void onApplicationEvent(ContextClosedEvent event) {
		LoginService.logout();
	}

	@Override
	public int getOrder() {
		return HIGHEST_PRECEDENCE + 2000;
	}
}